#include "../PreCompile.hpp"
#include "GCCOutputParser.hpp"

namespace BuildNG
{  
  void GccOutputLine::parse_gcc_output_line(const Glib::ustring &line,GccOutputLine &out)
  {
    const gchar *begin = line.c_str();
    const gchar *end = begin + line.bytes();
    
    // see if the line contains the string "error:" or "warning:". 
    // If so, it's interesting, if not, we just consider it noise.
    
    out.line_type = Noise;
    
    const gchar *colons[3] = {0};
    int num_colons = 0;
    const gchar *location_end = 0;
    const gchar *message_begin = 0;
    for(const gchar *c = begin;c != end;c++)
    {
      if(*c == ':')
      {
        if(num_colons == 3)
        {
          colons[0] = colons[1];
          colons[1] = colons[2];
          colons[2] = c;
        }
        else
        {
          colons[num_colons++] = c;
        }
      }
      
      if(compare_string_begin(c,end,"error:"))
      {
        location_end = c;
        message_begin = c + sizeof("error:") - 1;
        out.line_type = Error;
        break;
      }
      
      if(compare_string_begin(c,end,"warning:"))
      {
        location_end = c;
        message_begin = c + sizeof("warning:") - 1;
        out.line_type = Warning;
        break;
      }
    }
    
    if(out.line_type == Noise)
      return;

    assert(location_end);

    out.error_location.line_number = -1;
    out.error_location.column_number = -1;
    
    const gchar *file_name_end = num_colons ? colons[0] : location_end;
    for(int i = num_colons - 1;i >= 1;i--)
    {
      // see if the current part can be a line or column number
      gint32 number;
      TryParseIntRes parse_res = try_parse_int(colons[i - 1] + 1,colons[i],number);
      if(parse_res != TryParseIntRes_Success)
      {
        file_name_end = colons[i];
        break;
      }
      
      out.error_location.column_number = out.error_location.line_number;
      out.error_location.line_number = number;
    }
    
    out.error_location.file_name = Glib::ustring(begin,file_name_end - begin);
    trim(out.error_location.file_name);
    
    assert(message_begin != 0);
    out.msg = Glib::ustring(message_begin,end - message_begin);
    trim(out.msg);
    
  }
}
